package com.soulmate.gateway.config;

import com.soulmate.gateway.handler.GatewayRequestAccessDeniedHandler;
import com.soulmate.gateway.handler.GatewayRequestAuthenticationEntryPoint;
import com.soulmate.gateway.handler.GatewaySecurityErrorExceptionHandler;
import com.soulmate.gateway.handler.GatewaySecurityRepository;
import com.soulmate.gateway.manager.AuthorizationTokenAccessManager;
import lombok.AllArgsConstructor;
import org.springframework.cloud.gateway.filter.GatewayFilter;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.HttpMethod;
import org.springframework.security.config.annotation.web.reactive.EnableWebFluxSecurity;
import org.springframework.security.config.web.server.SecurityWebFiltersOrder;
import org.springframework.security.config.web.server.ServerHttpSecurity;
import org.springframework.security.web.server.SecurityWebFilterChain;

/**
 * @author huaiping
 */
@EnableWebFluxSecurity
@Configuration
@AllArgsConstructor
public class FluxWebSecurityConfig {
    private AuthorizationTokenAccessManager accessManager;
    private GatewaySecurityRepository securityRepository;
    private GatewayRequestAccessDeniedHandler gatewayRequestAccessDeniedHandler;
    private GatewayRequestAuthenticationEntryPoint gatewayRequestAuthenticationEntryPoint;

    @Bean
    public SecurityWebFilterChain springSecurityFilterChain(ServerHttpSecurity http) {
        http
                .authorizeExchange((authorize) -> authorize
                        .pathMatchers("/user/login").permitAll()
                        .pathMatchers(HttpMethod.OPTIONS).permitAll()
                        .anyExchange().access(accessManager)
                )
                .exceptionHandling((exceptionHandling) -> {
                    exceptionHandling.accessDeniedHandler(gatewayRequestAccessDeniedHandler);
                    exceptionHandling.authenticationEntryPoint(gatewayRequestAuthenticationEntryPoint);
                })
                .securityContextRepository(securityRepository)
                .csrf(ServerHttpSecurity.CsrfSpec::disable);
        return http.build();
    }


}
